/**
 * SSE (Server-Sent Events) 工具类
 * 用于处理Spring AI的流式响应
 */

// 事件类型定义
export interface SSEEvent {
  id?: string
  event?: string
  data: string
  retry?: number
}

// 事件监听器类型
export type SSEEventListener = (event: SSEEvent) => void

/**
 * 解析SSE流
 * @param reader 可读流的reader
 * @param onEvent 事件回调函数
 * @param onComplete 完成回调函数
 * @param onError 错误回调函数
 */
export async function parseSSEStream(
  reader: ReadableStreamDefaultReader<Uint8Array>,
  onEvent: SSEEventListener,
  onComplete?: () => void,
  onError?: (error: any) => void
): Promise<void> {
  const decoder = new TextDecoder()
  let buffer = ''

  try {
    while (true) {
      const { done, value } = await reader.read()

      if (done) {
        // 处理缓冲区中剩余的数据
        if (buffer.trim()) {
          const event = parseEvent(buffer)
          if (event) {
            onEvent(event)
          }
        }
        if (onComplete) onComplete()
        break
      }

      // 将新接收的数据添加到缓冲区
      buffer += decoder.decode(value, { stream: true })

      // 处理完整的事件
      const events = buffer.split('\n\n')
      buffer = events.pop() || '' // 保留最后一个可能不完整的事件

      for (const eventText of events) {
        if (eventText.trim()) {
          const event = parseEvent(eventText)
          if (event) {
            onEvent(event)
          }
        }
      }
    }
  } catch (error) {
    if (onError) onError(error)
    else console.error('SSE流解析错误:', error)
  }
}

/**
 * 解析单个SSE事件
 * @param eventText 事件文本
 * @returns 解析后的事件对象
 */
function parseEvent(eventText: string): SSEEvent | null {
  const lines = eventText.split('\n')
  const event: Partial<SSEEvent> = {
    data: ''
  }

  for (const line of lines) {
    if (!line.trim()) continue

    // 解析字段
    const colonIndex = line.indexOf(':')
    if (colonIndex === -1) continue

    const field = line.slice(0, colonIndex).trim()
    // 跳过第一个空格（如果有）
    const valueStart = colonIndex + 1 + (line[colonIndex + 1] === ' ' ? 1 : 0)
    const value = line.slice(valueStart)

    if (field === 'data') {
      event.data = (event.data || '') + value
    } else if (field === 'event') {
      event.event = value
    } else if (field === 'id') {
      event.id = value
    } else if (field === 'retry') {
      const retry = parseInt(value, 10)
      if (!isNaN(retry)) event.retry = retry
    }
  }

  return event as SSEEvent
}
